#include "TcpClientTransferSession.h"

TcpClientTransferSession::TcpClientTransferSession(string local_addr,
												   int local_port)
:ClientTransferSession(inet_addr(local_addr.c_str()), htons(local_port))
{
}

TcpClientTransferSession::~TcpClientTransferSession()
{

}

void TcpClientTransferSession::wait_for_recv()
{
	int bind_ret_val, listen_ret_val, recv_ret_val;
	int conn_count = 0;
	int conn_socket;
	struct sockaddr_in remote_addr;
	socklen_t remote_sockaddr_length = sizeof(remote_addr);
	pid_t pid;

	m_listen_socket = socket(PF_INET, SOCK_STREAM, 0);
	if(-1 == m_listen_socket) {
		cout<<"&TcpClientTransferSession::wait_for_recv: "
				"fail to create socket, program exit."<<endl
				<<"The failure reason is: "<<errno<<endl;
		exit(0);
	}

	bind_ret_val = bind(m_listen_socket, (struct sockaddr*)&m_server_addr,
						sizeof(struct sockaddr));
	if(-1 == bind_ret_val) {
		cout<<"&TcpClientTransferSession::wait_for_recv: "
			  "fail to bind socket to local address, program exit."<<endl;
		cout<<"&TcpClientTransferSession::wait_for_recv: "
			  "The failure reason is: "<<errno<<endl;
		exit(0);
	}

	listen_ret_val = listen(m_listen_socket, 3);
	if(-1 == listen_ret_val) {
		cout<<"&TcpClientTransferSession::wait_for_recv: "
				"fail to listen on the socket, program exit"<<endl;
		cout<<"&TcpClientTransferSession::wait_for_recv: "
				"The failure reason is: "<<errno<<endl;
		exit(0);
	}

	while(1) {
#ifdef DEBUG_TCP_CLIENT_TRANSFER
	  	cout<<"&TcpClientTransferSession::wait_for_recv: "
	  			"Listenning to socket......"<<endl;
	  	cout<<"&TcpClientTransferSession::wait_for_recv: "
	  			"The current maximum connection number is: "
	  			<<conn_count<<endl;
#endif

	  	conn_socket = accept(m_listen_socket, (struct sockaddr*)&remote_addr,
	  			&remote_sockaddr_length);
		if(-1 == conn_socket) {
			cout<<"&TcpClientTransferSession::wait_for_recv:"
					" fail to accept for clients, program exit"<<endl;
			cout<<"&TcpClientTransferSession::wait_for_recv: "
					"The failure reason is: "<<errno<<endl;
			continue;
		}
#ifdef DEBUG_TCP_CLIENT_TRANSFER
		cout<<"&TcpClientTransferSession::wait_for_recv: "
				"accpet a client"<<endl;
		cout<<"&TcpClientTransferSession::wait_for_recv: "
				"The address of client is: "<<inet_ntoa(remote_addr.sin_addr)<<endl;
		cout<<"&TcpClientTransferSession::wait_for_recv: "
				"The port of client is: "<<ntohs(remote_addr.sin_port)<<endl;
#endif

		conn_count ++;

		if( 0 == (pid = fork()) ) {
#ifdef DEBUG_TCP_CLIENT_TRANSFER
			cout<<"&TcpClientTransferSession::wait_for_recv: "
					"start a new child server process."<<endl;
#endif

			close(m_listen_socket);

			char recv_buf[100];
			while( 0 < (recv_ret_val = recv(conn_socket, recv_buf, 100, 0)) ) {
				recv_buf[recv_ret_val] = '\0';
				cout<<"&TcpClientTransferSession::wait_for_recv: "
						"Data received from remote host is: "<<endl;
				cout.write(recv_buf, recv_ret_val);
			}

			close(conn_socket);
			exit(0);
		}

		close(conn_socket);
	} //while(1)

	close(m_listen_socket);
}

int TcpClientTransferSession::recv_data(string filename)
{
	return 0;
}

int TcpClientTransferSession::send_data(string filename,
										   string remote_addr,
										   int remote_port)
{
	struct sockaddr_in remote_sockaddr;
	int conn_socket;
	int conn_ret_val, send_ret_val;
	char buf_send[100];
	FILE* pFile = NULL;

	memset(buf_send, 0, 100);

	remote_sockaddr.sin_family = AF_INET;
	remote_sockaddr.sin_addr.s_addr = inet_addr(remote_addr.c_str());
	remote_sockaddr.sin_port = htons(remote_port);

	conn_socket = socket(PF_INET, SOCK_STREAM, 0);
	if(-1 == conn_socket) {
		cout<<"&TcpClientTransferSession::send: "
				"Fail to create a socket"<<endl;
		return -1;
	}

	conn_ret_val = connect(conn_socket, (struct sockaddr*)&remote_sockaddr,
						   sizeof(struct sockaddr_in));
	if(-1  == conn_ret_val) {
		cout<<"&TcpClientTransferSession::send: "
				"Fail to connect remote host."<<endl;
		return -1;
	}

	pFile = fopen(filename.c_str(), "r");
	if(NULL == pFile) {
		cout<<"&TcpClientTransferSession::send: "
				"fail to open file, program exit."<<endl;
		return -1;
	}

	if(NULL != fgets(buf_send, 100, pFile)) {
		send_ret_val = send(conn_socket, buf_send, strlen(buf_send), 0);
		if(-1 == send_ret_val) {
			cout<<"&TcpClientTransferSession::send: "
					"Fail to send a file content to remote host"<<endl;
			return -1;
		}
	}

	close(conn_socket);

	return 0;
}


